package com.gitee.wsl.ext.base


import kotlin.random.Random


val Byte.Companion.SIZE: Int
    get() = Byte.SIZE_BITS

val Byte.Companion.BYTES: Int
    get() = Byte.SIZE_BYTES

const val BYTE_MASK = 0xFF
const val BYTE_BITS = 8

/** Constant `0x00` */
inline val Byte.Companion.ZERO: Byte get() = 0x0

/** Constant `0x01` */
inline val Byte.Companion.ONE: Byte get() = 0b1.toByte()

inline val Byte.Companion.SIGN: Byte get() = 0b1000_0000.toByte()

inline val Byte.Companion.SEVEN: Byte get() = 0b0111_1111.toByte()

/** Constant `0x00` */
 inline val Byte.Companion.OO: Byte get() = ZERO

/** Constant `0xFF` */
 inline val Byte.Companion.FF: Byte get() = -1

/** Constant `0x00u` */
 inline val UByte.Companion.ZERO: UByte get() = 0x0u

/** Constant `0x00u` */
 inline val UByte.Companion.OO: UByte get() = ZERO

/** Constant `0xFFu` */
 inline val UByte.Companion.FF: UByte get() = MAX_VALUE

/** [ClosedRange] of all valid [UByte] values. */
 inline val UByte.Companion.VALUE_RANGE: UIntRange get() = UByte.Companion.MIN_VALUE..UByte.Companion.MAX_VALUE

/** [ClosedRange] of all valid [Byte] values. */
 inline val Byte.Companion.VALUE_RANGE: IntRange get() = Byte.Companion.MIN_VALUE..Byte.Companion.MAX_VALUE


object ByteExt{
    /**
     * Convert char into uint8( we treat char as uint8 )
     *
     * @param b the byte to be converted
     * @return the char(uint8)
     */
    fun convertByte2Uint8(b: Byte): Char {
        // char will be promoted to int for char don't support & operator
        // & 0xff could make negatvie value to positive
        return (b.toInt() and 0xff).toChar()
    }

    /**
     * Convert byte[] into char[]( we treat char[] as uint8[])
     *
     * @param bytes the byte[] to be converted
     * @return the char[](uint8[])
     */
    fun convertBytes2Uint8s(bytes: ByteArray): CharArray {
        val len = bytes.size
        val uint8s = CharArray(len)
        for (i in 0 until len) {
            uint8s[i] = convertByte2Uint8(bytes[i])
        }
        return uint8s
    }


    /**
     * Put byte[] into char[]( we treat char[] as uint8[])
     *
     * @param destUint8s the char[](uint8[]) array
     * @param srcBytes   the byte[]
     * @param destOffset the offset of char[](uint8[])
     * @param srcOffset  the offset of byte[]
     * @param count      the count of dest, and the count of src as well
     */
    fun putbytes2Uint8s(
        destUint8s: CharArray, srcBytes: ByteArray,
        destOffset: Int, srcOffset: Int, count: Int
    ) {
        for (i in 0 until count) {
            destUint8s[destOffset + i] = convertByte2Uint8(srcBytes[srcOffset + i])
        }
    }


    /**
     * Split uint8 to 2 bytes of high byte and low byte. e.g. 20 = 0x14 should
     * be split to [0x01,0x04] 0x01 is high byte and 0x04 is low byte
     *
     * @param uint8 the char(uint8)
     * @return the high and low bytes be split, byte[0] is high and byte[1] is
     * low
     */
    @OptIn(ExperimentalStdlibApi::class)
    fun splitUint8To2bytes(uint8: Char): ByteArray {
        if (uint8.code < 0 || uint8.code > 0xff) {
            throw RuntimeException("Out of Boundary")
        }
        val hexString = uint8.code.toHexString()
        val low: Byte
        val high: Byte
        if (hexString.length > 1) {
            high = hexString.substring(0, 1).toInt(16).toByte()
            low = hexString.substring(1, 2).toInt(16).toByte()
        } else {
            high = 0
            low = hexString.substring(0, 1).toInt(16).toByte()
        }
        return byteArrayOf(high, low)
    }

    /**
     * Combine 2 bytes (high byte and low byte) to one whole byte
     *
     * @param high the high byte
     * @param low  the low byte
     * @return the whole byte
     */
    fun combine2bytesToOne(high: Byte, low: Byte): Byte {
        if (high < 0 || high > 0xf || low < 0 || low > 0xf) {
            throw RuntimeException("Out of Boundary")
        }
        return (high.toInt() shl 4 or low.toInt()).toByte()
    }

    /**
     * Combine 2 bytes (high byte and low byte) to
     *
     * @param high the high byte
     * @param low  the low byte
     * @return the char(u8)
     */
    fun combine2bytesToU16(high: Byte, low: Byte): Char {
        val highU8 = convertByte2Uint8(high)
        val lowU8 = convertByte2Uint8(low)
        return (highU8.code shl 8 or lowU8.code).toChar()
    }

    /**
     * Generate the random byte to be sent
     *
     * @return the random byte
     */
    private fun randomByte(): Byte {
        return (127 - Random.nextInt(256)).toByte()
    }

    /**
     * Generate the random byte to be sent
     *
     * @param len the len presented by u8
     * @return the byte[] to be sent
     */
    fun randomBytes(len: Char): ByteArray {
        val data = ByteArray(len.code)
        var i = 0
        while (i < len.code) {
            data[i] = randomByte()
            i++
        }
        return data
    }

    fun genSpecBytes(len: Char): ByteArray {
        val data = ByteArray(len.code)
        var i = 0
        while (i < len.code) {
            data[i] = '1'.code.toByte()
            i++
        }
        return data
    }

    /**
     * Generate the random byte to be sent
     *
     * @param len the len presented by byte
     * @return the byte[] to be sent
     */
    fun randomBytes(len: Byte): ByteArray {
        val u8 = convertByte2Uint8(len)
        return randomBytes(u8)
    }

    /**
     * Generate the specific byte to be sent
     *
     * @param len the len presented by byte
     * @return the byte[]
     */
    fun genSpecBytes(len: Byte): ByteArray {
        val u8 = convertByte2Uint8(len)
        return genSpecBytes(u8)
    }

    /*fun parseBssid(bssidBytes: ByteArray, offset: Int, count: Int): String {
        val bytes = ByteArray(count)
        System.arraycopy(bssidBytes, offset, bytes, 0, count)
        return parseBssid(bytes)
    }*/

    /**
     * parse "24,-2,52,-102,-93,-60" to "18,fe,34,9a,a3,c4"
     * parse the bssid from hex to String
     *
     * @param bssidBytes the hex bytes bssid, e.g. {24,-2,52,-102,-93,-60}
     * @return the String of bssid, e.g. 18fe349aa3c4
     */
    @OptIn(ExperimentalStdlibApi::class)
    fun parseBssid(bssidBytes: ByteArray): String {
        val sb = StringBuilder()
        var k: Int
        var hexK: String
        var str: String
        for (bssidByte in bssidBytes) {
            k = 0xff and bssidByte.toInt()
            hexK = k.toHexString()
            str = if (k < 16) "0$hexK" else hexK
            println(str)
            sb.append(str)
        }
        return sb.toString()
    }

}


fun Byte.getBit(pos:Int):Int {
    // 确保位置有效
    require(pos in 0..7) { "Bit position must be between 0 and 7" }

    return (this.toInt() shr pos) and 1
}


//fun Byte.toHex(): String = String.format("%02X", this)


//infix fun Byte.xor(other: Byte): Byte = xor(other.toInt())

infix fun Byte.xor(other: Int): Byte = toInt().xor(other).toByte()

infix fun Byte.and(other: Int): Int = toInt().and(other)
//infix fun Byte.and(other: Byte): Byte = and(other.toInt()).toByte()

//infix fun Byte.or(other: Byte): Byte = or(other.toInt())

infix fun Byte.or(other: Int): Byte = toInt().or(other).toByte()



